package com.ews.onlineexchange.endpoint;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.ejb.Asynchronous;
import javax.enterprise.event.Observes;
import javax.enterprise.event.TransactionPhase;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.lang3.StringUtils;

import com.ews.onlineexchange.model.Bulletin;
import com.ews.onlineexchange.model.ChooseType;
import com.ews.onlineexchange.model.Trade;
import com.ews.onlineexchange.model.TradeStatus;
import com.ews.onlineexchange.service.qualifier.EndChooseWsEvent;
import com.ews.onlineexchange.service.qualifier.SendWsEvent;
import com.ews.onlineexchange.service.qualifier.StartChooseWsEvent;

@ServerEndpoint(value = "/bulletinEnd/{bulletinId}")
public class TestEndPoint {
	static ArrayList<Integer> list = new ArrayList<Integer>();
	@Inject
	EntityManager entityManager;
	
	@Inject
	private SessionRegistry sessionRegistry;
	
	@OnOpen
	public void onOpen(Session session, @PathParam("bulletinId") String bulletinId, EndpointConfig endpointConfig) {
		session.setMaxIdleTimeout(60 * 60 * 1000);
		sessionRegistry.add(session);
	}	
	
	@OnClose
	public void onClose(Session session, @PathParam("bulletinId") String bulletinId, CloseReason closeReason) {
		sessionRegistry.remove(session);
	}	
	
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {
		if (StringUtils.isBlank(message))
			return;
		
		Bulletin bulletin = entityManager.find(Bulletin.class, session.getPathParameters().get("bulletinId"));
		if (bulletin == null) {
			return ;
		}
		
		if (!bulletin.getTradeStatus().equals(TradeStatus.Agreed) && !bulletin.getTradeStatus().equals(TradeStatus.Waiting))
			return ;
						
		for (Session session2 : sessionRegistry.getAll(session.getPathParameters().get("bulletinId"))) {		
			if (session2.isOpen()) {
				session2.getBasicRemote().sendText(message);
//				System.out.println(session2.getId());
			}
		}
	}
	
//	@Transactional(value = TxType.REQUIRED)
	@Asynchronous
	public void send(@Observes(during = TransactionPhase.AFTER_COMPLETION) @SendWsEvent Bulletin b) throws IOException {
		if (b == null) {
			return ;
		}
		
		if (!b.getTradeStatus().equals(TradeStatus.Agreed) && !b.getTradeStatus().equals(TradeStatus.Waiting))
			return ;
		
		String message = null;
		if (b.getWayOfChoose().equals(ChooseType.Manual) ||  b.getWayOfChoose().equals(ChooseType.Random )||  
				b.getWayOfChoose().equals(ChooseType.Price)||  b.getWayOfChoose().equals(ChooseType.Average)) {
			message = b.getSuccessTrade().getSupplier().getId();
			System.out.println(b.getProjectName());
			System.out.println(b.getSuccessTrade().getSupplier().getId());
			System.out.println(b.getSuccessTrade().getSupplier().getCnname());
		}else if (b.getWayOfChoose().equals(ChooseType.Best)) {
			String seeds = new String();
			for (Trade trade : b.getBestTrades()) {
				seeds = seeds.concat(trade.getSupplier().getId()).concat(",");
			}
			if (seeds.length() > 0)
				seeds = seeds.substring(0, seeds.length() - 1);
			message = seeds;
		}
//		else {//随机
//			String seeds = new String();
//			seeds = seeds.concat(bulletin.getSuccessTrade().getId()).concat(",");
//			for (Trade trade : bulletin.getBackupTrades()) {
//				seeds = seeds.concat(trade.getSupplier().getId()).concat(",");
//			}
//			if (seeds.length() > 0)
//				seeds = seeds.substring(0, seeds.length() - 1);
//			message = seeds;
//		}
		if( null != sessionRegistry.getAll(b.getId()) ) {
			for (Session session2 : sessionRegistry.getAll(b.getId())) {		
				if (session2.isOpen()) {
					session2.getBasicRemote().sendText(message);
				}
			}
		}
		
	}
	
	
	public void sendStartChoose(@Observes(during = TransactionPhase.AFTER_COMPLETION) @StartChooseWsEvent Bulletin b) throws IOException {

//		String bulletinId = b.getId();
//		Bulletin bulletin = entityManager.find(Bulletin.class, bulletinId);
		Bulletin bulletin = b;
		String bulletinId = b.getId();
		if (bulletin == null) {
			return ;
		}
		if(new Date().before(bulletin.getChooseTime())) return ;
		if (!bulletin.getTradeStatus().equals(TradeStatus.Agreed) && !bulletin.getTradeStatus().equals(TradeStatus.Waiting))
			return ;
		
		String message = "startChoose";
		
		if( null != sessionRegistry.getAll(bulletinId) ) {
			for (Session session2 : sessionRegistry.getAll(bulletinId)) {		
				if (session2.isOpen()) {
					session2.getBasicRemote().sendText(message);
				}
			}
		}
		
	}
	
	public void sendEndChoose(@Observes(during = TransactionPhase.AFTER_COMPLETION) @EndChooseWsEvent Bulletin b) throws IOException {
//		String bulletinId = b.getId();
//		Bulletin bulletin = entityManager.find(Bulletin.class, bulletinId);
		Bulletin bulletin = b;
		String bulletinId = b.getId();
		if (bulletin == null) {
			return ;
		}
		if(new Date().before(bulletin.getChooseTime())) return ;
		if (!bulletin.getTradeStatus().equals(TradeStatus.Agreed) && !bulletin.getTradeStatus().equals(TradeStatus.Waiting))
			return ;
		
		String message = "endChoose";
		
		if( null != sessionRegistry.getAll(bulletinId) ) {
			for (Session session2 : sessionRegistry.getAll(bulletinId)) {		
				if (session2.isOpen()) {
					session2.getBasicRemote().sendText(message);
				}
			}
		}
		
	}

	public static void main(String[] args) {
//		Map<String, Set<Integer>> integers = Collections.synchronizedMap(new HashMap<>());
//		Map<String, CopyOnWriteArraySet<Integer>> integers = Collections.synchronizedMap(new HashMap<>());
		final Map<String, Set<Integer>> integers = new HashMap<>();
//		CopyOnWriteArraySet<Integer> ints1 = new CopyOnWriteArraySet<>();
		Set<Integer> ints1 = new HashSet<>();
		ints1.add(1);
		ints1.add(2);
		integers.put("1", ints1);
//		Set<Integer> ints2 = new HashSet<>();
//		ints2.add(1);
//		ints2.add(2);
//		integers.put("2", ints2);
		 Thread thread1 = new Thread(){
	            public void run() {
	            	synchronized (integers) {
	            		 Iterator<Integer> iterator = integers.get("1").iterator();
	 	                while(iterator.hasNext()){
	 	                    Integer integer = iterator.next();
	 	                    System.out.println(integer);
	 	                    try {
	 	                        Thread.sleep(100);
	 	                    } catch (InterruptedException e) {
	 	                        e.printStackTrace();
	 	                    }
	 	                }
					}
	               
	            };
	        };
	        Thread thread2 = new Thread(){
	            public void run() {
	            	synchronized (integers) {
	            		 Iterator<Integer> iterator = integers.get("1").iterator();
	 	                while(iterator.hasNext()){
	 	                    Integer integer = iterator.next();
	 	                    if(integer==2)
	 	                        iterator.remove(); 
	 	                }
					}
	            	
	            };
	        };
	        thread1.start();
	        thread2.start();
		
		
	}
}
